﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using CCompiler;

namespace CCompilerUI {
    public partial class CompileForm : Form {
        private string sourceFile = "";
        private CCompiler.CCompiler compiler;

        public CompileForm(string sourceFile) {
            this.sourceFile = sourceFile;

            InitializeComponent();
        }

        private void ShowSymbolTableTree(TreeNode node) {
            SymbolTable symTab = (SymbolTable)node.Tag;
            TreeNode[] childNodes = new TreeNode[symTab.childScopes.Count];

            for (int i = 0; i < childNodes.Length; i++) {
                SymbolTable child = (SymbolTable)symTab.childScopes[i];
                childNodes[i] = new TreeNode("scope");
                childNodes[i].Tag = symTab.childScopes[i];

                if (((SymbolTable)symTab.childScopes[i]).childScopes.Count > 0)
                    ShowSymbolTableTree(childNodes[i]);

                node.Nodes.Add(childNodes[i]);
            }
        }

        private void CompileForm_Load(object sender, EventArgs e) {
            compiler = new CCompiler.CCompiler(sourceFile);
            compiler.Compile();

            for (int i = 0; i < compiler.errorsList.Count; i++) {
                ErrorsListBox.Items.Add(compiler.errorsList[i]);
            }

            IntermediateTextBox.Text = compiler.intermediateCode;
            AssemblyTextBox.Text = compiler.assemblyCode;
            AssemblerOutputTextBox.Text = compiler.assemblerOutput;

            TreeNode root = new TreeNode("Root");
            root.Tag = compiler.symbolTable;
            ShowSymbolTableTree(root);
            ScopeTree.Nodes.Add(root);
            root.ExpandAll();

            Text = "C Compiler - " + (sourceFile == "" ? "untitled" : new FileInfo(sourceFile).Name);
        }

        private void RunButton_Click(object sender, EventArgs e) {
            compiler.Run();
        }

        private void CloseButton_Click(object sender, EventArgs e) {
            Close();
        }

        private void ScopeTree_AfterSelect(object sender, TreeViewEventArgs e) {
            SymbolTable node = (SymbolTable)e.Node.Tag;
            SymTabGrid.Rows.Clear();

            foreach (Symbol symbol in node.table.Values) {
                object[] details;

                if (symbol is VariableSymbol) {
                    VariableSymbol varSymbol = (VariableSymbol)symbol;

                    details = new object[] { varSymbol.lexeme, varSymbol.code, varSymbol.type,
                                             varSymbol.kind, varSymbol.isArray, varSymbol.offset,
                                             varSymbol.size, varSymbol.elemSize };
                } else if (symbol is FunctionSymbol) {
                    FunctionSymbol funcSymbol = (FunctionSymbol)symbol;

                    details = new object[] { funcSymbol.lexeme, funcSymbol.code, funcSymbol.returnType };
                } else {
                    details = new object[] { symbol.lexeme, symbol.code };
                }

                SymTabGrid.Rows.Add(details);
            }

            SymTabGrid.Sort(SymTabGrid.Columns["OffsetCol"], ListSortDirection.Ascending);
        }
    }
}
